package com.poetize.plus.service.impl;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.poetize.plus.entity.dto.ChangeForbiddenDTO;
import com.poetize.plus.entity.dto.RegisterDTO;
import com.poetize.plus.entity.dto.UserDTO;
import com.poetize.plus.entity.dto.UserUiDTO;
import com.poetize.plus.entity.dto.page.UserPageDTO;
import com.poetize.plus.entity.po.User;
import com.poetize.plus.entity.vo.UserPageVO;
import com.poetize.plus.entity.vo.UserVO;
import com.poetize.plus.mapper.UserMapper;
import com.poetize.plus.service.UserService;
import com.poetize.plus.utils.BaseConstant;
import com.poetize.plus.utils.LoginUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author zuosy
 * @created 2024/3/29 9:54
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final RedisTemplate<String, Object> redisTemplate;

    // 这个是 mail 依赖提供给我们的发送邮件的接口
    private final JavaMailSender mailSender;

    private final PasswordEncoder passwordEncoder;

    @Value("${spring.mail.nickname}")
    private String nickname;

    @Value("${spring.mail.username}")
    private String username;

    @Override
    public Page<UserPageVO> userPage(UserPageDTO userPageDTO) {
        Page<User> userPage = lambdaQuery()
                .like(StringUtils.hasText(userPageDTO.getUsername()), User::getUsername, userPageDTO.getUsername())
                .eq(Objects.nonNull(userPageDTO.getForbidden()), User::getForbidden, userPageDTO.getForbidden())
                .eq(StringUtils.hasText(userPageDTO.getEmail()), User::getEmail, userPageDTO.getEmail())
                .page(Page.of(userPageDTO.getCurrent(), userPageDTO.getSize()));

        Page<UserPageVO> result = new Page<>();
        if (CollectionUtils.isEmpty(userPage.getRecords())){
            return result;
        }
        result.setTotal(userPage.getTotal());
        result.setRecords(UserPageVO.convertPageList(userPage.getRecords()));
        return result;
    }

    @Override
    public Boolean changeForbidden(ChangeForbiddenDTO changeForbiddenDTO) {
        if (changeForbiddenDTO.id() == -200L){
            throw new IllegalArgumentException("禁止操作超级管理员信息");
        }
        return baseMapper.update(lambdaUpdate()
                .eq(User::getId, changeForbiddenDTO.id())
                .set(User::getForbidden, changeForbiddenDTO.forbidden())) > 0;
    }

    @Override
    public UserVO queryUser(Long id) {
        User user = baseMapper.selectById(id);
        return UserVO.convert(user);
    }

    @Override
    public Boolean updateUser(UserDTO userDTO) {
        if (userDTO.id() == -200L){
            throw new IllegalArgumentException("禁止操作超级管理员信息");
        }
        User checkName = lambdaQuery()
                .eq(User::getUsername, userDTO.username())
                .ne(User::getId, userDTO.id())
                .one();
        if (Objects.nonNull(checkName)){
            throw new IllegalArgumentException("用户名已存在");
        }
        User user = UserDTO.convertDTO(userDTO);
        return baseMapper.updateById(user) > 0;
    }

    @Override
    public Boolean deleteUser(Long id) {
        if (id == -200L){
            throw new IllegalArgumentException("禁止操作超级管理员信息");
        }
        return baseMapper.deleteById(id) > 0;
    }

    @Override
    public Boolean sendCode(String email) {
        boolean checkEmail = Validator.isEmail(email);
        if (!checkEmail){
            throw new IllegalArgumentException("请输入正确邮箱");
        }
        Object restrict = redisTemplate.opsForValue().get(email + BaseConstant.Redis.MAIL_RESTRICT);
        if (Objects.nonNull(restrict)){
            throw new IllegalArgumentException("操作频繁,一分钟后重试");
        }
        User emailExist = lambdaQuery()
                .eq(User::getEmail, email)
                .one();
        if (Objects.nonNull(emailExist)){
            throw new IllegalArgumentException("邮箱已被注册");
        }
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(nickname + '<' + username + '>');
        message.setTo(email);
        message.setSubject("欢迎注册我的博客");
        String code = RandomUtil.randomNumbers(6);
        //设置验证码有效期
        redisTemplate.opsForValue().set(email + BaseConstant.Redis.MAIL_VALIDITY, code, 5, TimeUnit.MINUTES);
        //设置验证码操作间隔
        redisTemplate.opsForValue().set(email + BaseConstant.Redis.MAIL_RESTRICT, "1", 1, TimeUnit.MINUTES);
        String content = "【验证码】您的验证码为：" + code + " 。 验证码五分钟内有效，逾期作废。如因网络问题导致验证码接收延迟，则以最后一次验证码为准！";
        message.setText(content);
        mailSender.send(message);
        return true;
    }

    @Override
    public Boolean register(RegisterDTO registerDTO) {
        Object redisCode = redisTemplate.opsForValue().get(registerDTO.email() + BaseConstant.Redis.MAIL_VALIDITY);
        if (Objects.isNull(redisCode)){
            throw new IllegalArgumentException("验证码已失效");
        }
        String code = redisCode.toString();
        if (!code.equals(registerDTO.code())){
            throw new IllegalArgumentException("验证码不正确");
        }
        User checkUsername = lambdaQuery()
                .eq(User::getUsername, registerDTO.username())
                .one();
        if (Objects.nonNull(checkUsername)){
            throw new IllegalArgumentException("用户名已存在");
        }
        User checkEmail = lambdaQuery()
                .eq(User::getEmail, registerDTO.email())
                .one();
        if (Objects.nonNull(checkEmail)){
            throw new IllegalArgumentException("邮箱已被注册");
        }
        User user = new User();
        user.setUsername(registerDTO.username());
        user.setPassword(passwordEncoder.encode(registerDTO.password()));
        user.setRole("common");
        user.setEmail(registerDTO.email());
        user.setGender("0");
        user.setForbidden(false);
        user.setCreateBy(registerDTO.username());
        user.setUpdateBy(registerDTO.username());
        baseMapper.insert(user);
        return  true;
    }

    @Override
    public UserVO userInfo() {
        String userName = LoginUtils.getLoginUserName();
        User user = lambdaQuery().eq(User::getUsername, userName).one();
        return UserVO.convert(user);
    }

    @Override
    public Boolean modified(UserUiDTO userUiDTO) {
        User user = UserUiDTO.convertDTO(userUiDTO);
        return baseMapper.updateById(user) > 0;
    }
}
